/**
 * PESA2MNO_main.java
 *
 * @author Juanjo Durillo
 * @version 1.0
 * 
 * This class executes the PESA2MNO algorithm
 */
package ufpr.mestrado.ais.metaheuristics.pesa2mno;

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Logger;

import jmetal.base.Algorithm;
import jmetal.base.Operator;
import jmetal.base.Problem;
import jmetal.base.SolutionSet;
import jmetal.qualityIndicator.QualityIndicator;
import jmetal.util.Configuration;
import jmetal.util.JMException;
import ufpr.mestrado.ais.base.operator.bw.AR;
import ufpr.mestrado.ais.base.operator.crossover.SinglePointCrossoverMNO;
import ufpr.mestrado.ais.base.operator.mutation.BitFlipMutationMNO;
import ufpr.mestrado.ais.problems.mno.DTLZ.DTLZMNO2;

public class PESA2MNO_main {
	public static Logger logger_; // Logger object
	public static FileHandler fileHandler_; // FileHandler object

	/**
	 * @param args
	 *            Command line arguments. The first (optional) argument
	 *            specifies the problem to solve.
	 * @throws JMException
	 * @throws IOException
	 * @throws SecurityException
	 *             Usage: three options -
	 *             jmetal.metaheuristics.mocell.MOCell_main -
	 *             jmetal.metaheuristics.mocell.MOCell_main problemName -
	 *             jmetal.metaheuristics.mocell.MOCell_main problemName
	 *             ParetoFrontFile
	 */
	public static void main(String[] args) throws JMException, IOException,
			ClassNotFoundException {
		Problem problem; // The problem to solve
		Algorithm algorithm; // The algorithm to use
		Operator crossover; // Crossover operator
		Operator mutation; // Mutation operator

		QualityIndicator indicators; // Object to get quality indicators

		// Logger object and file to store log messages
		logger_ = Configuration.logger_;
		fileHandler_ = new FileHandler("PESA2MNO_main.log");
		logger_.addHandler(fileHandler_);

		indicators = null;

		problem = new DTLZMNO2("BinaryReal", 12, 3, 0.35);

		algorithm = new PESA2MNO(problem);

		indicators = new QualityIndicator(problem, args[0]);

		// Algorithm parameters
		algorithm.setInputParameter("populationSize", 200);
		algorithm.setInputParameter("archiveSize", 300);
		algorithm.setInputParameter("bisections", 5);
		algorithm.setInputParameter("maxEvaluations", 300);

		// Mutation and Crossover for Real codification
		// crossover = CrossoverFactory.getCrossoverOperator("SBXCrossover");
		/*
		 * crossover = new SBXCrossoverMNO();
		 * crossover.setParameter("probability", 0.9);
		 * crossover.setParameter("distributionIndex", 20.0);
		 * 
		 * mutation = MutationFactory.getMutationOperator("PolynomialMutation");
		 * mutation.setParameter("probability", 1.0 /
		 * problem.getNumberOfVariables());
		 * mutation.setParameter("distributionIndex", 20.0);
		 */
		//algorithm.addOperator("bw_operator", new AR());

		// Mutation and Crossover Binary codification

		crossover = new SinglePointCrossoverMNO();
		crossover.setParameter("probability", 0.9);

		mutation = new BitFlipMutationMNO();
		mutation.setParameter("probability",
				1.0 / problem.getNumberOfVariables());

		// Add the operators to the algorithm
		algorithm.addOperator("crossover", crossover);
		algorithm.addOperator("mutation", mutation);

		// Execute the Algorithm
		long initTime = System.currentTimeMillis();
		SolutionSet population = algorithm.execute();
		long estimatedTime = System.currentTimeMillis() - initTime;
		System.out.println("Total execution time: " + estimatedTime);

		// Result messages
		logger_.info("Total execution time: " + estimatedTime + "ms");
		logger_.info("Variables values have been writen to file VAR");
		population.printVariablesToFile("result/VAR.var");
		logger_.info("Objectives values have been writen to file FUN");
		population.printObjectivesToFile("result/FUN.fun");

		if (indicators != null) {
			logger_.info("Quality indicators");
			logger_.info("Hypervolume: "
					+ indicators.getHypervolume(population));
			logger_.info("GD         : " + indicators.getGD(population));
			logger_.info("IGD        : " + indicators.getIGD(population));
			logger_.info("Spread     : " + indicators.getSpread(population));
			logger_.info("Epsilon    : " + indicators.getEpsilon(population));

			/*
			 * int evaluations = ((Integer) algorithm
			 * .getOutputParameter("evaluations")).intValue();
			 * logger_.info("Speed      : " + evaluations + " evaluations");
			 */
		} // if
	}// main
} // PESA2MNO_main
